package lar.game.gamestate;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.EventListener;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;

import javax.microedition.khronos.opengles.GL11;

import lar.game.physics.Rotation;
import lar.game.physics.Vector;
import lar.system.engine.GameLoop;
import lar.system.engine.MainProgram;
import lar.system.engine.TouchListener;
import lar.system.engine.UI;
import lar.system.network.BluetoothConnection;
import lar.system.opengl.GLButton;
import lar.system.opengl.GLColor;
import lar.system.opengl.GLImage;
import lar.system.opengl.GLImageList;
import lar.system.opengl.GLRButton;
import lar.system.opengl.GLString;
import lar.system.opengl.GLStringList;
import lar.system.opengl.GLTextField;
import lar.system.sound.Music;
import lar.system.sound.Sound;

import lar.system.R;

import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.view.MotionEvent;

public class MainMenu implements GameState 
{
	
	private BluetoothAdapter mBluetoothAdapter;
	private Set<BluetoothDevice> pairedDevices = new LinkedHashSet<BluetoothDevice>();;
	private List<BluetoothDevice> visibleDevices = new LinkedList<BluetoothDevice>();
	
	private GLStringList devicesList; 
	private GLString devicesStr;
	private GLRButton discoverButton;
	private GLRButton pairButton;
	private GLRButton connectButton;
	private BroadcastReceiver mReceiver;
	private BluetoothSocket mmSocket;
	private boolean connected = false;
	
	
	private BluetoothConnection connection = null;
	
	public MainMenu() 
	{
		float asp = MainProgram.glSurfaceView.getAspectRatio();
		devicesList = new GLStringList(R.drawable.basefont, new float[]{-asp+0.5f, 0.35f}, new float[]{0.5f, 0.5f}, 0.07f);
		devicesStr = new GLString(R.drawable.basefont, "Visible:", new float[]{-asp+0.1f, 0.9f}, 0.07f);
		devicesStr.setColor(GLColor.GREEN.asFloatArray());
		discoverButton = new GLRButton(new float[]{-asp+0.3f, -0.3f}, new float[]{0.3f, 0.1f}, "Discover", 0.06f, GLColor.RED, new GLRButton.RButtonListener() 
		{
			public void event() 
			{
				Discover();
			}
		});
		pairButton = new GLRButton(new float[]{-asp+0.3f, -0.5f}, new float[]{0.3f, 0.1f}, "Pair", 0.06f, GLColor.ORANGE, new GLRButton.RButtonListener() 
		{
			public void event() 
			{
				Pair();
			}
		});
		connectButton = new GLRButton(new float[]{-asp+0.3f, -0.7f}, new float[]{0.3f, 0.1f}, "Connect", 0.06f, GLColor.GREEN, new GLRButton.RButtonListener() 
		{
			public void event() 
			{
				Connect();
			}
		});
		
		
		GoBluetooth();
		getPairedDevices();
	}
	
	/**
	 * @param connection
	 */
	public MainMenu(BluetoothConnection connection)
	{
		this();
		this.connection = connection;
		this.connected = true;
		connectButton.setString("Disconnect");
	}
	
	private void Pair()
	{
		int sel = devicesList.getSelectedIndex();
		if(sel < 0) return;
		BluetoothDevice bd = visibleDevices.get(sel);
		getPairedDevices();
		if(pairedDevices.contains(bd)) 
		{
			MainProgram.MessageBox("Already paired");
			return; 
		}
		try 
		{
            boolean isBonded = createBond(bd);
            if(isBonded)
            {
                MainProgram.MessageBox("Successfully paired");
            }
        } catch (Exception e) 
        {
           MainProgram.MessageBox("Failed to pair");
        }//connect(bdDevice);
		
	}
	
	private void Connect()
	{
		if(connected)
		{
			try
			{
				mmSocket.close();
			} catch (IOException e) {}
			MainProgram.MessageBox("Disconnected.");
			connected = false;
			connectButton.setString("Connect");
			if(connection != null)
			{
				connection.close();
				connection = null;
			}
			return;
		}
		int sel = devicesList.getSelectedIndex();
		if(sel < 0) return;
		BluetoothDevice bd = visibleDevices.get(sel);
		if(!pairedDevices.contains(bd))
		{
			MainProgram.MessageBox("Pair first");
			return;
		}
		try 
		{
			mmSocket = bd.createRfcommSocketToServiceRecord(bd.getUuids()[0].getUuid());
			mBluetoothAdapter.cancelDiscovery();
			mmSocket.connect();
			
		} catch (IOException e) 
		{
			try 
			{
				mmSocket.close();
			} catch (IOException e1) {}
			MainProgram.MessageBox("Something went wrong...");
			e.printStackTrace();
			return;
		}
		connected = true;
		connection = new BluetoothConnection(mmSocket);
		Thread t = new Thread(connection);
		t.start();
		if(mReceiver != null) MainProgram.currentActivity.unregisterReceiver(mReceiver);
		MainProgram.MessageBoxStrict("Connected!", new OnClickListener() 
		{
			public void onClick(DialogInterface dialog, int which) 
			{
				MainProgram.glSurfaceView.ClearListeners();
				MainProgram.gameLoop.ChangeState(new FadeOutFadeIn(MainMenu.this, new FunMenu(connection)));
			}
		});
	}
	
	private void GoBluetooth()
	{
		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
		if (mBluetoothAdapter == null) 
		{
		    MainProgram.MessageBox("Bluetooth not detected on device");
		    return;
		}
		if (!mBluetoothAdapter.isEnabled()) 
		{
		    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
		    MainProgram.currentActivity.startActivityForResult(enableBtIntent, 1);
		}
	}
	
	private void Discover()
	{
		if(!mBluetoothAdapter.isEnabled())
		{
			MainProgram.MessageBox("Enable Bluetooth first!");
			return;
		}
		for(int i = 0; i < devicesList.size(); i++) devicesList.removeElement(0);
		visibleDevices.clear();
		if(mReceiver != null) MainProgram.currentActivity.unregisterReceiver(mReceiver);
		mReceiver = new BroadcastReceiver() 
		{
		    public void onReceive(Context context, Intent intent) 
		    {
		        String action = intent.getAction();
		        // When discovery finds a device
		        if (BluetoothDevice.ACTION_FOUND.equals(action)) 
		        {
		            // Get the BluetoothDevice object from the Intent
		            //Log.d("R", "found!!");
		        	BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
		            // Add the name and address to an array adapter to show in a ListView
		            for(int i = 0; i < devicesList.size(); i++) if(devicesList.getCoreElement(i).getAsciiString().equals(device.getName())) return;
		        	visibleDevices.add(device);
		            devicesList.addElement(device.getName());
		        }
		    }
		};
		// Register the BroadcastReceiver
		IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
		MainProgram.currentActivity.registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
		mBluetoothAdapter.startDiscovery();
		
	}
	
	void getPairedDevices()
	{
		pairedDevices = mBluetoothAdapter.getBondedDevices();
		if(!mBluetoothAdapter.isEnabled())
		{
			return;
		}
	}
	
	
	public boolean removeBond(BluetoothDevice btDevice)  
    throws Exception  
    {  
        Class btClass = Class.forName("android.bluetooth.BluetoothDevice");
        Method removeBondMethod = btClass.getMethod("removeBond");  
        Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);  
        return returnValue.booleanValue();  
    }


    public boolean createBond(BluetoothDevice btDevice)  
    throws Exception  
    { 
        Class class1 = Class.forName("android.bluetooth.BluetoothDevice");
        Method createBondMethod = class1.getMethod("createBond");  
        Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);  
        return returnValue.booleanValue();  
    }  
	
	public String getVersion()
	{
		return MainProgram.VERSION_STRING;
	}
	
	public void gameFrame() 
	{
		
	}

	public void Draw(GL11 gl) 
	{
		devicesList.Draw(gl);
		devicesStr.Draw(gl);
		discoverButton.Draw(gl);
		pairButton.Draw(gl);
		connectButton.Draw(gl);
		
	}

	@Override
	public void onPause() {
		
	}

	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean CheckBounds(float x, float y) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onDestroy() 
	{
		if(mReceiver != null) MainProgram.currentActivity.unregisterReceiver(mReceiver);
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onBack() 
	{
		if(mReceiver != null) MainProgram.currentActivity.unregisterReceiver(mReceiver);
		MainProgram.glSurfaceView.ClearListeners();
		MainProgram.gameLoop.Terminate();
	}
	
	
	
	
	
}
